/**
 *  消消乐的棋盘
 * 
 */
class XXLBoard {
    // 构造函数
    public constructor(xCnt: number, yCnt: number, types: number[]) {
        let self = this;
        self._x_cnt = xCnt;
        self._y_cnt = yCnt;
        self._node_types = types;
        console.log("XXLBoard types : " + types);
        self.initEvent();
    }

    // 横轴能消除的节点
    public get conditionsX(){ return this._conditionsX; }
    // 竖轴能消除的节点
    public get conditionsY(){ return this._conditionsY; }
    // 横轴数量
    public get x_Cnt(){ return this._x_cnt; }
    // 竖轴数量
    public get y_Cnt(){ return this._y_cnt; }
    // 所有节点
    public get nodes(){ return this._nodes; }   

    // 生成节点
    public createNodes() {
        let self = this;
        self.clearAll();

        for (let i = 0; i < self._y_cnt; i++) {
            for (let j = 0; j < self._x_cnt; j++) {
                let val = self.randGetNode();
                var node = new XXLNode(j, i, val);
                self._nodes[i][j] = node;
            }
        }
    }

    // 清理
    private clearAll() {
        let self = this;
        self._nodes = null;
        self._nodes = new Array<Array<XXLNode>>();
        for (let i = 0; i < self._y_cnt; i++) {
            self._nodes[i] = [];
        }
        self._nodes.push([]);
    }

    // 通过坐标获取节点
    public getNodeByPos(x: number, y: number): XXLNode {
        if(x < 0 || y < 0) return null;
        return this._nodes[y][x];
    }
    

    // 随机获取类型
    private randGetNode(): number {
        let self = this;
        var cnt = self._node_types.length;
        var randNum = (Math.random() * 10) % cnt;
        randNum = Math.floor(randNum);

        return self._node_types[randNum];
    }    

    // 检测棋盘移动一步能否消除
    private updateMoveCheck() : boolean{

        return false;
    }

/*
    // 下落交换两个节点
    private dropSwapeNode(node:XXLNode, index:number){
        if(node == null || index == 0) return;

        let self = this;
        let y = node.y_pos + index;
        if(y >= self.y_Cnt) return;
        
        let x = node.x_pos;
        let n = self.nodes[y][x];
        n.clone(node);
        self.swape(n, node);
        JcEvent.ins.NotifyEvent(XXLEventName.dropItem, node, index);
    }

    // 获取下落的数量<当返回值为0时不可下落>
    private getDropCount(node:XXLNode):number{
        if(node == null || node.state == 0) return 0;

        let self = this;
        let x = node.x_pos;
        let y = node.y_pos;
        let maxY = self.y_Cnt - 1;

        let temp = 0;
        for(let i = maxY; i > y; i--){
            let n = self.nodes[i][x];
            if(n.state == 0){
                temp = i - y;
                break;
            }
        }
        return temp;
    } 
    */

    // 重新生成
    private randomAddChild(){
        console.log("开始创建！-----------------2");
        let self = this;

        let maxX = self.x_Cnt;
        let enableCnt = 0;
        for(let i = 0; i < maxX; i++){
            let node = self.nodes[0][i];
            if(node.state == 0){
                let val = self.randGetNode();
                node.val = val;
                node.state = 1;
                JcEvent.ins.NotifyEvent(XXLEventName.createItem, node);
                // self.dropNodeByX(i);
                console.log("开始创建！-----------------3" + node._color);
            }else if(node.state == 1){
                enableCnt += 1;
            }
        }

        if(enableCnt == maxX){
            return;
        }else{
            // self.randomAddChild();
        }
    }

    private dropNodeByX(xIndex : number){
        let self = this;
        let maxY = self.y_Cnt - 1;

        let point : number = maxY;
        
        while(true){
            let node = self.nodes[point][xIndex];
            if(node.state == 0){
                let index = point - 1;                
                while(index >= 0){
                    let nextNode = self.nodes[index][xIndex];
                    if(nextNode.state == 1){
                        self.swape(node, nextNode);                        
                        JcEvent.ins.NotifyEvent(XXLEventName.dropItem, node, nextNode);
                        point -= 1;
                        break;
                    }else if(nextNode.state == 0){
                        index -= 1;
                    }
                }
                if(index < 0) break;
            }else if(node.state == 1){
                point -= 1;
            }
            if(point < 0) break;
        }
    }

    // 下落所有的节点
    private dropAll(){
        console.log("执行下落！");
        let self = this;
        let xCnt = self.x_Cnt;

        for(let i = 0; i < xCnt; i++){
            self.dropNodeByX(i);
        }
    }

    // 消除棋盘上能消除的节点
    private xcBoard(){
        let self = this;

        if(!self.isHasXCCondition()) return;

        self.xcConditions(self._conditionsX);
        self.xcConditions(self._conditionsY);

        // 消除完成后,下落所有节点
        // self.dropAll();
    }

    // 消除能消除的条件列表
    private xcConditions(conditionList : Array<XCCondition>){
        if(conditionList == null || conditionList.length == 0) return;
        let self = this;

        conditionList.forEach(element => {
            self.xcCondition(element);
        });        
    }

    // 是否有立刻能消除的节点
    private isHasXCCondition() : boolean{
        let self = this; 

        // self.updateCheck();
        let isHasX = false;
        let isHasY = false;

        if(self._conditionsX.length > 0 && self._conditionsX[0].canXC){
            isHasX = true;
        }

        if(self._conditionsY.length > 0 && self._conditionsY[0].canXC){
            isHasY = true;
        }

        return isHasX || isHasY;
    }

    // 消除能消除的节点
    private xcCondition(condition : XCCondition){
        if(condition == null) return;

        let list = condition.list;
        for (let i = 0; i < list.length; i++) {
            let node = list[i];
            if(node.state == 0){
                continue;
            }else if(node.state == 1){
                node.xcSelf();
                JcEvent.ins.NotifyEvent(XXLEventName.xcItem, node.x_pos, node.y_pos);
            }
        }
    }

    // 全局向右检测是否有消除的节点
    private boardCheckX(index : number){        
        let self = this;
        if(index >= (self.x_Cnt * self.y_Cnt)) return;

        let xp = index % self.x_Cnt;
        let yp = Math.floor(index / self.y_Cnt);
        let node = self._nodes[yp][xp];
        let conditionx = self.checkNodeRight(node, XCCondition.CreateCondition(node, 1));

        if(conditionx.canXC){
            this._conditionsX.push(conditionx);
        }
        index += conditionx.list.length;
        this.boardCheckX(index);
    }

    // 全局向下检测是否有消除的节点
    private boardCheckY(index : number){
        let self = this;
        if(index >= (self.x_Cnt * self.y_Cnt)) return;

        let xp = Math.floor(index / self.x_Cnt);
        let yp = index % self.y_Cnt;

        let node = self._nodes[yp][xp];
        let conditionx = self.checkNodeDown(node, XCCondition.CreateCondition(node, 2));

        if(conditionx.canXC){
            this._conditionsY.push(conditionx);
        }
        index += conditionx.list.length;
        this.boardCheckY(index);
    }

    // 向右检测是否有消除的节点
    private checkNodeDown(node : XXLNode, condition : XCCondition):XCCondition{        
        let self = this;
        let xp = node.x_pos;
        let yp = node.y_pos;
        let len = self.y_Cnt;

        let lyp = yp + 1;
        if(lyp < len){
            let dNode = self._nodes[lyp][xp];
            if(dNode.val == node.val){
                condition.list.push(dNode);
                self.checkNodeDown(dNode, condition);                
            }
        }
        return condition;
    }

    // 向下检测是否有消除的节点
    private checkNodeRight(node : XXLNode, condition : XCCondition):XCCondition{
        let self = this;
        let xp = node.x_pos;
        let yp = node.y_pos;
        let len = self.x_Cnt;

        let lxp = xp + 1;
        if(lxp < len){
            let lNode = self._nodes[yp][lxp];
            if(lNode.val == node.val){
                condition.list.push(lNode);
                self.checkNodeRight(lNode, condition);                
            }
        }
        return condition;
    }

    // 检测能否消除
    private isCanXC(node: XXLNode): boolean {
        let self = this;
        let canX = self.xCheck(node);
        let canY = self.yCheck(node);

        let xcX : boolean = false;
        let xcY : boolean = false;
        if(canX != null){
            xcX = canX.canXC;
        }
        if(canY != null){
            xcY = canY.canXC;
        }

        let canXC = xcX || xcY;

        return canXC;
    }

    // 交换后检测X轴是否有能消除的节点
    private xCheck(node: XXLNode):XCCondition{
        let self = this;
        let posY = node.y_pos;
        let val = node.val;

        let preIndex = node.x_pos - 1;
        let nxtIndex = node.x_pos + 1;

        let preB = true;
        let nxtB = true;

        let preNodes : Array<XXLNode> = new Array<XXLNode>();
        let nxtNodes : Array<XXLNode> = new Array<XXLNode>();
        
        for(let j = 0; j < self._x_cnt; j++)
        {
            let preNode : XXLNode;
            let nxtNode : XXLNode;
            
            if(preIndex >= 0 && preB)
            {
                preNode = self.nodes[posY][preIndex];
                preIndex -= 1;
            }else{
                preB = false;
            }
            
            if(nxtIndex < self._x_cnt && nxtB)
            {
                nxtNode = self.nodes[posY][nxtIndex];
                nxtIndex += 1;
            }else{
                nxtB = false;
            }

            if(preB && preNode.val == val){
                // 继续往前查询
                preNodes.unshift(preNode);
            }
            else{
                preB = false;
            }

            if(nxtB && nxtNode.val == val){
                // 往后查询
                nxtNodes.push(nxtNode);
            }else{
                nxtB = false;
            }

            if(!preB && !nxtB) break;            
        }

        if(preNodes.length > 0){
            preNodes.push(node);
        }
        else if(nxtNodes.length > 0){
            nxtNodes.unshift(node);
        }

        let condition : XCCondition;
        let preLen = preNodes.length;
        let nxtLen = nxtNodes.length;
        if(preLen == 0 && nxtLen > 0){
            condition = new XCCondition(nxtNodes, 2);
        }else if(preLen > 0 && nxtLen == 0){
            condition = new XCCondition(preNodes, 2);
        }else if(preLen > 0 && nxtLen > 0){
            preNodes.concat(nxtNodes);
            condition = new XCCondition(preNodes, 2);
        }else{
            condition = null;
        }

        return condition;
    }

    // 交换后检测Y轴是否有能消除的节点
    private yCheck(node: XXLNode):XCCondition{
        let self = this;
        let posX = node.x_pos;
        let val = node.val;

        let preIndex = node.y_pos - 1;
        let nxtIndex = node.y_pos + 1;

        let preB = true;
        let nxtB = true;

        let preNodes : Array<XXLNode> = new Array<XXLNode>();
        let nxtNodes : Array<XXLNode> = new Array<XXLNode>();
        
        for(let j = 0; j < self._y_cnt; j++)
        {
            let preNode : XXLNode;
            let nxtNode : XXLNode;
            
            if(preIndex >= 0 && preB)
            {
                preNode = self.nodes[preIndex][posX];
                preIndex -= 1;
            }
            else{
                preB = false;
            }
            
            if(nxtIndex < self._x_cnt && nxtB)
            {
                nxtNode = self.nodes[nxtIndex][posX];
                nxtIndex += 1;
            }else{
                nxtB = false;
            }

            if(preB && preNode.val == val){
                // 继续往前查询
                preNodes.unshift(preNode);
            }
            else{
                preB = false;
            }

            if(nxtB && nxtNode.val == val){
                // 往后查询
                nxtNodes.push(nxtNode);
            }else{
                nxtB = false;
            }

            if(!preB && !nxtB) break;            
        }

        if(preNodes.length > 0){
            preNodes.push(node);
        }
        else if(nxtNodes.length > 0){
            nxtNodes.unshift(node);
        }

        let condition : XCCondition;
        let preLen = preNodes.length;
        let nxtLen = nxtNodes.length;
        if(preLen == 0 && nxtLen > 0){
            condition = new XCCondition(nxtNodes, 2);
        }else if(preLen > 0 && nxtLen == 0){
            condition = new XCCondition(preNodes, 2);
        }else if(preLen > 0 && nxtLen > 0){
            preNodes.concat(nxtNodes);
            preLen = preNodes.length;
            condition = new XCCondition(preNodes, 2);
        }else{
            condition = null;
        }

        return condition;
    } 

    // 全局检测能否可以消除
    private updateCheck(){
        let self = this;

        self._conditionsX = null;
        self._conditionsX = new Array<XCCondition>();

        self._conditionsY = null;
        self._conditionsY = new Array<XCCondition>();

        let index = 0;
        self.boardCheckX(index);
        
        index = 0;
        self.boardCheckY(index);
        console.log("check all");

        let canXC = self.isHasXCCondition();
        if(canXC){
            self.xcBoard();
        }else{
            // for(let i = 0; i < self.y_Cnt; i++){                
            //     for(let j = 0; j < self._x_cnt; j++){
            //         let node = self.nodes[i][j];                    
            //     }
            // }
            console.log(self.nodes);
        }
    }

    // 能否交换(<true> 已经交换过 </true>, <false> 未交换 </false>)
    public canSwape(node1: XXLNode, node2: XXLNode): boolean {
        if(node1 == null || node2 == null) return false;
        let self = this;

        let sn1 = new XXLNode(0, 0, 0);
        sn1.x_pos = node1.x_pos;
        sn1.y_pos = node1.y_pos;
        sn1.val = node1.val;

        let sn2 = new XXLNode(0, 0, 0);
        sn2.x_pos = node2.x_pos;
        sn2.y_pos = node2.y_pos;
        sn2.val = node2.val;
        
        JcEvent.ins.NotifyEvent(XXLEventName.swapeItem, sn1, sn2);
        self.swape(node1, node2);

        return true;

        /*
        let n1CanXC = self.isCanXC(node1);
        let n2CanXC = self.isCanXC(node2);

        if(n1CanXC || n2CanXC) {
            self.updateCheck();
            JcEvent.ins.NotifyEvent(XXLEventName.swapeItem, sn1, sn2);
            return true;
        }
        self.swape(node1, node2);
        JcEvent.ins.NotifyEvent(XXLEventName.dontSwape, sn1, sn2);

        return false;
        */
    }

    // 交换两个节点的位置
    public swape(node1: XXLNode, node2: XXLNode){
        if(node1 == null || node2 == null) return;
        let self = this;
        
        node1.swapePos(node2);

        self._nodes[node1.y_pos][node1.x_pos] = node1;
        self._nodes[node2.y_pos][node2.x_pos] = node2;
    }

    // 交换两个节点
    private onSwapeNode(en : string, node1 : XXLNode, node2 : XXLNode){
        if(node1 == null || node2 == null) return;

        let self = this;
        let isCanSwape = self.canSwape(node1, node2);
        
        // if(self.canSwape(node1, node2)){
        //     JcEvent.ins.NotifyEvent(XXLEventName.swapeItem, node1, node2);
        // }else{
        //     JcEvent.ins.NotifyEvent(XXLEventName.dontSwape, node1, node2);
        // }
    }

    private onDropNode(en : string){
        let self = this;
        self.dropAll();

        // self.randomAddChild();
        // self.updateCheck();
    }

    private onDropNodeEnd(en : string){
        let self = this;
        console.log("开始创建！-----------------1");
        self.randomAddChild();
    }

    private initEvent(){
        let self = this;
        JcEvent.ins.RegistEvent(XXLEventName.swapeNode, self.onSwapeNode, self);
        JcEvent.ins.RegistEvent(XXLEventName.checkAll, self.updateCheck, self);
        JcEvent.ins.RegistEvent(XXLEventName.dropNode, self.onDropNode, self);
        JcEvent.ins.RegistEvent(XXLEventName.dropNodeEnd, self.onDropNodeEnd, self);
    }

    // 读表配置
    private _x_cnt: number;
    private _y_cnt: number;
    // 选择几种参加游戏的节点类型
    private _node_types: Array<number>;
    // 所有的节点
    private _nodes: Array<Array<XXLNode>>;
    // 横轴能消除的节点
    private _conditionsX : Array<XCCondition>;
    // 竖轴能消除的节点
    private _conditionsY : Array<XCCondition>;
}